package com.qf.controller;

import com.qf.captcha.CaptchaCodeManager;
import com.qf.pojo.DtsAdmin;
import com.qf.service.DtsPermissionService;
import com.qf.service.DtsRoleService;
import com.qf.util.Base64;
import com.qf.util.ResponseUtil;
import com.qf.util.UUID;
import com.qf.util.VerifyCodeUtils;
import org.apache.shiro.SecurityUtils;
import org.apache.shiro.authc.CredentialsException;
import org.apache.shiro.authc.LockedAccountException;
import org.apache.shiro.authc.UnknownAccountException;
import org.apache.shiro.authc.UsernamePasswordToken;
import org.apache.shiro.subject.Subject;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;

import javax.servlet.http.HttpSession;
import java.io.ByteArrayOutputStream;
import java.io.IOException;
import java.util.HashMap;
import java.util.Map;
import java.util.Set;

/**
 * @author 千锋教育
 * @Company http://www.mobiletrain.org/
 * @Version 1.0
 */
@RestController
@RequestMapping("/admin/auth")
//@CrossOrigin("http://localhost")
public class DtsAdminAuthController {


    @Autowired
    DtsRoleService roleService;
    @Autowired
    DtsPermissionService permissionService;

    @GetMapping("/info")
    public Object info(){
        Subject subject=SecurityUtils.getSubject();
        DtsAdmin admin = (DtsAdmin)subject.getPrincipal();
        Map<String,Object> data = new HashMap<>();

        Set<String> roles = roleService.findRoleByIds(admin.getRoleIds());
        data.put("roles", roles);
        data.put("name", admin.getUsername());
        Set<String> perms = permissionService.findPermByIds(admin.getRoleIds());
        data.put("perms", perms);
        data.put("avator", admin.getAvatar());
        return ResponseUtil.ok(data);
    }

    /**
     * 登录功能 -- 思路
     *  1. 校验验证码
     *  2. 登录操作
     *
     *
     * @RequestBody: 解析json为 java对象
     * 使用时机： post请求方式，数据类型为json， 请求体传参
     * Map: 如果前端的json数据格式与pojo不匹配， 则使用map
     * Pojo: 如果前端的json数据格式与pojo匹配，则使用pojo
     * @param map
     * @return
     */
    @RequestMapping("/login")
    public Object login(@RequestBody Map<String,String> map, HttpSession session){
        //获取请求参数
        String code = map.get("code"); //从前端用户输入的
        String password = map.get("password");
        String username = map.get("username");
        String uuid = map.get("uuid");

        //校验验证码
        //从服务器（缓存）获取生成的验证码
        String cachedCaptcha = CaptchaCodeManager.getCachedCaptcha(uuid);
        if(code == null || !code.equalsIgnoreCase(cachedCaptcha)) {
            return ResponseUtil.fail(-1, "验证码已过期或验证码错误!!");
        }


        //(shiro)登录操作
        Subject subject = SecurityUtils.getSubject();

        UsernamePasswordToken token = new UsernamePasswordToken(username,password);

        //subject.login(token); 登录方法
        try {
            subject.login(token);
        } catch (UnknownAccountException e) {
            //在控制台打印错误的堆栈信息,方便解决问题的
            e.printStackTrace();
            return ResponseUtil.fail(-1, "未知的账户");
        } catch (LockedAccountException e){
            e.printStackTrace();
            return ResponseUtil.fail(-1, "账户已锁定");
        } catch (CredentialsException e){
            e.printStackTrace();
            return ResponseUtil.fail(-1, "密码错误");
        }


        System.out.println(subject.hasRole("超级管理员"));
        System.out.println(subject.isPermitted("admin:category:read"));

        return ResponseUtil.ok(session.getId());
    }


    @GetMapping("/captchaImage")
    public Object captchaImage() throws IOException {
        //1. 生成验证码
        //生成指定位数的验证码
        String code = VerifyCodeUtils.generateVerifyCode(2);
        //创建输出流对象
        ByteArrayOutputStream outputStream = new ByteArrayOutputStream();

        //生成验证码图片
        VerifyCodeUtils.outputImage(111,33,outputStream ,code);
        //把输出流的内容转换为字节数组, 方便传输, 为了安全，要对验证码图片数据进行加密
//        outputStream.toByteArray()

        //唯一标识
        String uuid = UUID.randomUUID().toString();

        //把验证码存储到缓存中
        CaptchaCodeManager.addToCache(uuid, code, 5 );


        Map<String,Object> data = new HashMap<>();
        data.put("img", Base64.encode(outputStream.toByteArray()));
        data.put("uuid",  uuid);

        //这里对应了 前端需要的数据结构
        return ResponseUtil.ok(data);
    }
}
